#include "server.h"

Server::Server(){
	newLockIndex = 0;
	newCVIndex = 0;
	//serverDataLock = new ServerLock("ServerDataLock",0,this);
	serverLockTable = new Table(MAX_NUM_SERVLOCKS);
	serverCVTable = new Table(MAX_NUM_SERVCONDS);
	//serverMVTable = new Table(MAX_NUM_MONVARS);
	//serverLockIndex = 1;
	readyPktQueue = new List();
	readyMailQueue = new List();
	//monVar = new int[MAX_NUM_MONVARS];
	char* name;
	/*
	for (int i=1; i<(MAX_NUM_SERVLOCKS+1); i++){
		name = new char [20];
		sprintf(name,"ServerLock%d",i);
		serverLock[i] = new ServerLock(name,i,this);
	}
	for (int i=0; i<(MAX_NUM_SERVCONDS); i++){
		name = new char [20];
		sprintf(name,"ServerCond%d",i);
		serverCond[i] = new ServerCondition(name,i,this);
	}
	for(int i=0; i<(MAX_NUM_MONVARS); i++){
		mon
		Var[i] = 0;
	}
	*/
}
Server::~Server(){
	
}
    
void Server::ReceiveMessage(int type, int from, int lock, int cond, int ind, int val){
	switch (type) {
		default:
			printf("Unknown type - shutting down.\n");
		//user prog requested acquire
		case LOCK_ACQUIRE: 
			if (serverLockTable->Get(lock) == 0){
				DEBUG('n',"ERROR: Lock at index %d is equal to null.\n",lock);
				AddToReadyQueue(from);
				return;
			}
			printf("Addr %d requested lock acquire for lock %d \n",from,lock);
			ServerLock* temp = ((ServerLock*) serverLockTable->Get(lock));
			printf("here1\n");
			temp->SAcquire(from);
			printf("here2\n");
			/*
			if (lock == SERVERDATALOCK){
				serverDataLock->SAcquire(from);
			}
			else{
				if (lock <= MAX_NUM_SERVLOCKS && lock > 0){
					serverLock[lock]->SAcquire(from);
				}
			}
			*/
		break;
		//user prog requested release
		case LOCK_RELEASE:
			printf("Addr %d requested lock release for lock %d \n",from,lock);
			((ServerLock*) serverLockTable->Get(lock))->SRelease(from, false);
			/*
			if (lock == SERVERDATALOCK){
				serverDataLock->SRelease(from, false);
			}
			else{
				if (lock <= MAX_NUM_SERVLOCKS && lock > 0){
					serverLock[lock]->SRelease(from, false);
				}
			}
			*/
		break;
		case LOCK_ISHELDBYCURRENT://server
			//not implemented for proj 3
			printf("Lock isHeldByCurrent requested\n");
		break;
		//user prog requested wait
		case COND_WAIT:
			printf("Addr %d requested cond wait for lock %d cond %d\n",from,lock,cond);
			((ServerCondition*) serverCVTable->Get(cond))->SWait(((ServerLock*) serverLockTable->Get(lock)), from);
			/*
			if (lock == SERVERDATALOCK){
				serverCond[cond]->SWait(serverDataLock, from);
			}
			else{
				if ((lock <= MAX_NUM_SERVLOCKS && lock > 0) && (cond < MAX_NUM_SERVCONDS && lock >= 0)){
					serverCond[cond]->SWait(serverLock[lock], from);
				}
			}
			*/
		break;
		//user prog requested signal
		case COND_SIGNAL:
			printf("Addr %d requested cond signal for lock %d cond %d\n",from,lock,cond);
			((ServerCondition*) serverCVTable->Get(cond))->SSignal(((ServerLock*) serverLockTable->Get(lock)), from);

			/*
			if (lock == SERVERDATALOCK){
				serverCond[cond]->SSignal(serverDataLock, from);
			}
			else{
				if ((lock <= MAX_NUM_SERVLOCKS && lock > 0) && (cond < MAX_NUM_SERVCONDS && lock >= 0)){
					serverCond[cond]->SSignal(serverLock[lock], from);
				}
			}
			*/
		break;
		//user prog requested broadcast
		case COND_BROADCAST:
			printf("Addr %d requested cond broadcast for lock %d cond %d\n",from,lock,cond);
			((ServerCondition*) serverCVTable->Get(cond))->SBroadcast(((ServerLock*) serverLockTable->Get(lock)), from);
			/*
			if (lock == SERVERDATALOCK){
				serverCond[cond]->SBroadcast(serverDataLock, from);
			}
			else{
				if ((lock <= MAX_NUM_SERVLOCKS && lock > 0) && (cond < MAX_NUM_SERVCONDS && lock >= 0)){
					serverCond[cond]->SBroadcast(serverLock[lock], from);
				}
			}
			*/
		break;
		//user prog requested to update MV
		/*
		case UPDATE_MV:
			printf("Addr %d requested to update monVar[%d] to %d\n",from,ind,val);
			serverMVTable->Update(ind,val);
			//monVar[ind]=val;
			AddToReadyQueue(from);
		break;
		//user prog requested to retreive MV
		case RETRIEVE_MV:
			printf("Addr %d requested to retreive monVar[%d]=%d\n",from,ind,monVar[ind]);
			AddToReadyQueue(from);
		break;
		*/
		case CREATE_LOCK:
			//if(lock < 0 || lock > MAX_NUM_SERVLOCKS){
			//	printf("Lock %d is out of bounds (only locks 0-10 are valid)\n",lock);
			//}
			//else{
				printf("Addr %d requested to create lock\n",from);
				//if (lock == SERVERDATALOCK){
				//	printf("ServerDataLock already created\n");
				//}
				//else{
				ServerLock* newLock = new ServerLock("Lock", 1, this);
				newLockIndex = serverLockTable->Put(newLock);
				//}
				AddToReadyQueue(from);
			//}
		break;
		case CREATE_CV:
			//if(lock < 0 || lock > MAX_NUM_SERVLOCKS){
			//	printf("Lock %d is out of bounds (only locks 0-10 are valid)\n",lock);
			//}
			//else{
				printf("Addr %d requested to create lock\n",from);
				//if (lock == SERVERDATALOCK){
				//	printf("ServerDataLock already created\n");
				//}
				//else{
				ServerCondition* newCV = new ServerCondition("CV", 1, this);
				newCVIndex = serverCVTable->Put(newCV);
				//}
				AddToReadyQueue(from);
			//}
		break;
	}
}

void Server::AddToReadyQueue(int to){
	readyPktQueue->Append((void*)to);
}

int Server::GetNextPktDest(){
	if (readyPktQueue->IsEmpty()){
		return -1;
	}
	else {
		return (int)readyPktQueue->Remove();
	}
}

/*
int Server::GetMV(int index){
	return serverMVTable->Get(index);
}
*/

int Server::GetNewLockIndex(){
	return newLockIndex;
}

int Server::GetNewCVIndex(){
	return newCVIndex;
}

